//------------------------------------------------------------------------------
// winestore version 15
// author Luo Xu on 2014.08.02
// Tested successfully.
//
// modified by zhangwei on 2014.08.02
// - Add config.base
// - Rename Wine as WineModel in order to distinguish wine object and wine model object.
// - Refactoring the source code.
// modified by zhangwei in 2014.09
// - Refacotored the structure.
// modified by zhangwei on 2014.10.08
// - This version is derived from version 10 directly. The developer revised the 
//   whiole program structure and make it better than ever. Hope it can be a good
//   template for new modules.
// modified by zhangwei on 2014.12.31
// - Revised. Eliminate some old source code. Also simplified some coding.
// modified by zhangwei on 2015.02.13
// - Copied "webapp/winestore-v14*.*" to "webapp/examples/winestore/winestore-v15.*",
//   and upgrade the css, js and rest backend URL with new relative link.
//   This version is the same as v14 except above modifications.
//	 Tested Ok
// - Add reference to "bootstrap.min.js" though it's not mandatory now.
//------------------------------------------------------------------------------

// Save the URL prefix of the current webapp

var config = {
    //base: "api/"
    //base: "mvc/"
	base1: "../../mvc/fdb/",
	base2: "../../mvc/",
	//base: "/site/mvc"
};

//------------------------------------------------------------------------------
// Service Layer
// for business logic including data access and network communication. 
//------------------------------------------------------------------------------

window.NodeModel = Backbone.Model.extend({
	// you can also uses urlRoot: config.base +　"api/wines". In this way, this 
	// page and js file can be moved into sub folders. 
	urlRoot : config.base1 + "nodes",
	
	defaults : {
		"id" : null,
		"owner": "",
		"originname" : "",
		"curname" : "",
		"storageid" : "",
		"nodetype" : "",
		"contenttype" : "",
		"attribute" : "",
		"properties": "",
		"size" : "",
		"objectstate" : "",
		"rowstate" : "",
		"upduser" : "",
		"upddate" : "",
		"crtuser" : "",
		"crtdate" : "",
//		"picture" : ""                
	},

	initialize : function() {
		this.bind('validate', function(model, error) {
			alert(error);
		});
	},
	

	getCustomUrl: function (method) {
        switch (method) {
        	case 'read':
        	    return this.urlRoot + '/'+this.id+'.dat/';
        	    break;
    	    case 'update':
	            return this.urlRoot + '/'+this.id+'.dat/properties';
	            break;
            case 'create':
                return this.urlRoot + '/new/data';
        	case 'delete':
        	    return this.urlRoot + '/'+this.id+'.dat/';
        	    break;
        
        }
    },
    // Now lets override the sync function to use our custom URLs
    sync: function (method, model, options) {
        options || (options = {});
        options.url = this.getCustomUrl(method.toLowerCase());
        
        // Lets notify backbone to use our URLs and do follow default course
        return Backbone.sync.apply(this, arguments);
    },

	

	// The returned string will be popup by the browser to notify the user.
	validate : function(attributes) {
		if (attributes.storageid == '') {
			alert("storageid can't be null");
			return "storageid can't be null"; 
		}

		try{
			JSON.parse(attributes.properties);
		}catch (e){
			alert("更新失败！"+e.name + ": " + e.message);
			return e.message;
		}
	}
});



window.FtpFileModel = Backbone.Model.extend({

	urlRoot : config.base2 + "ftproot",
	
	defaults : {
		"id" : "",
		"uploadtimestring" : "",
		"originname" : "",
		"filesize" : "",
		"properties" : "",            
	},

	idAttribute: "originname",
    
    getCustomUrl: function (method) {
        switch (method) {
            case 'save':
                return this.urlRoot + '/'+this.id + '/operation';
                break;
            case 'update':
                return this.urlRoot + '/'+this.id + '/operation';
                break;
            case 'delete':
                return this.urlRoot + '/'+this.id + '/';
                break;
        }
    },

    sync: function (method, model, options) {
        options || (options = {});
        options.url = this.getCustomUrl(method.toLowerCase());
        
        // Lets notify backbone to use our URLs and do follow default course
        return Backbone.sync.apply(this, arguments);
    },

	initialize : function() {
		this.bind('validate', function(model, error) {
			alert(error);
		});
	},
	
	// The returned string will be popup by the browser to notify the user.
	validate : function(attributes) {
		if (attributes.originname == '') {
			alert("原始文件名不能为空"); 
			return "filename could not be empty.";
		}
		try{
			JSON.parse(attributes.properties);
		}catch (e){
			alert("属性json格式输入不对！"+e.name + ": " + e.message);
			return e.message;
		}
	}
});



window.HttpUploadModel = Backbone.Model.extend({

	urlRoot : config.base1,
	
	defaults : {
		"id" : null,
		"properties" : "",   
		"objectstate" : "",         
	},

	idAttribute: "id",
    
    getCustomUrl: function (method) {
        switch (method) {
        	case 'create':
                return this.urlRoot + 'new';
                break;
            case 'save':
                return this.urlRoot + 'new';
                break;
            case 'update':
                return this.urlRoot + 'new';
                break;
        }
    },

    sync: function (method, model, options) {
        options || (options = {});
        options.url = this.getCustomUrl(method.toLowerCase());
        
        // Lets notify backbone to use our URLs and do follow default course
        return Backbone.sync.apply(this, arguments);
    },

	initialize : function() {
		this.bind('validate', function(model, error) {
			alert(error);
		});
	},
	
	// The returned string will be popup by the browser to notify the user.
	validate : function(attributes) {
		try{
			JSON.parse(attributes.properties);
		}catch (e){
			alert("属性json格式输入不对！"+e.name + ": " + e.message);
			return e.message;
		}
	}
});

// window.WineCollectionModel = Backbone.Collection.extend({
//	model : WineModel,
//	url : "api/wines"
// });

// modified by luoxu
// The "client" mode means the collection are fully on the client side. 
// The mode should be "client" to enable client side caching for paging.
//
window.PageableNodeCollection = Backbone.PageableCollection.extend({
	model : NodeModel,
	url : config.base1 + "nodes",
	state : {
		pageSize : 10
	},
	mode : "client" 
});


window.PageableFtpFileCollection = Backbone.PageableCollection.extend({
	model : FtpFileModel,
	url: config.base2 + "ftproot",
	state : {
		pageSize : 10
	},
	mode : "client"
});

//------------------------------------------------------------------------------
// View Layer
// for user interaction. Including render the data in the models to webpage
// and accepting the page input to model for saving. 
//------------------------------------------------------------------------------

// In order to guarantee releasing resources when view is closed
//
Backbone.View.prototype.close = function () {
    console.log('Closing view ' + this);
    if (this.beforeClose) {
        this.beforeClose();
    }
    this.remove();
    this.unbind();
};



window.NodeView = Backbone.View.extend({
	
    events: {
        "change input": "onInputChange",
		"click .save": "onSaveWine",
		"click .cancel": "onCancel"
    },

    initialize: function() {
    	this.template = _.template($('#tpl_itemdetail').html());
		this.model.on("change", this.render, this);
    },
    
    render: function() {
		$(this.el).html(this.template(this.model.toJSON()));
		console.log(this.el);
		console.log(this.template(this.model.toJSON()));
		console.log($(this.el));
		return this;
    },

    onInputChange: function(event) {
        var target = event.target;
        console.log('changing ' + target.id + ' from: ' + target.defaultValue + ' to: ' + target.value);
    },

	onSaveWine: function() {
		this.model.set({
		    id: $('#id').val(),
			originname: $('#originname').val(),
			storageid: $('#storageid').val(),
			size: $("#size").val(),
			properties: $('#properties').val()
		});
		if(!this.model.isValid()){
			alert("storageid can't be empty!");
			return false;
		}
		
		// http://stackoverflow.com/questions/16256635/backbone-model-saving-and-callback-issues
		// The model must belong to the pagable wine list
		this.model.save(null, {
			success: function() {
				alert("save successfully!");
				app.navigate('', {trigger: true});
			},
			error: function(error){
				console.log("exception encountered when save data" );
			}
		});

		return false;
	},
	
	onCancel : function(){
		app.navigate('', {trigger :true});
	}
});




BackgridColumns = [{
		// enable the select-all extension of the backgrid component
		name : "",
		cell : "select-row",
		headerCell : "select-all"
	}, {
		name : "id",
		label : "ID",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	}, {
		name : "originname",
		label : "Originname",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	}, {
		name : "storageid",
		label : "Storageid",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	},{
		name : "properties",
		label : "Properties",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	},{
		name : "crtdate",
		label : "Crtdate",
		editable : false,
		formatter : new Backgrid.DatetimeFormatter({
			fromRaw: function (rawdata,model){
                   var newDate = new Date();
                   newDate.setTime(rawdata);
                   var year=newDate.getYear()+1900;     
	               var month=newDate.getMonth()+1;     
	               var date=newDate.getDate();     
	               var hour=newDate.getHours();     
	               var minute=newDate.getMinutes();     
	               var second=newDate.getSeconds();     
	              return year+"-"+month+"-"+date+"   "+hour+":"+minute+":"+second; 
                   
                   //return newDate.toLocaleString().replace(/年|月/g, "-").replace(/上午|下午/g,"").replace(/日/g, " "); 
			},
		}),
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	}, {
		name : "delete",
		label : "",
		editable : false,
		cell : Backgrid.Cell.extend({
			template : _.template('<button class="btn btn-danger">Delete</button>'),
			events : {
				"click" : "onDeleteRow"
			},
			onDeleteRow : function(e) {
				e.preventDefault();
				 if(confirm("确定要删除吗？"))
                {
					this.model.destroy({
						success : function(model, response) {
							alert('Wine deleted successfully ' );
						},
						error: function(error){
								console.log("exception encountered when delete data" );
						}
				    });
				}
				return false;
			},
			render : function() {
				this.$el.html(this.template());
				this.delegateEvents();
				return this;
			}
		})
	}, {
		name : "edit",
		label : "",
		editable : false,
		cell : Backgrid.Cell.extend({
			template : _.template('<a href="#wines/<%= this.model.id %>" class="btn btn-primary">Edit</a>'),
			events : {
				"click" : "onEditRow",
			},

			onEditRow : function(e) {
				e.preventDefault();
				//app.navigate("wines/:id", {trigger: true}); 
				app.navigate("wines/" + this.model.id, {trigger: true}); 
				return false;
			},

			render : function() {
				this.$el.html(this.template());
				this.delegateEvents();
				return this;
			}
		})
	}];





FtpBackgridColumns = [{
		// enable the select-all extension of the backgrid component
		name : "",
		cell : "select-row",
		headerCell : "select-all"
	}, {
		name : "id",
		label : "Id",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	},{
		name : "uploadtimestring",
		label : "Uploadtime",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	}, {
		name : "originname",
		label : "Originname",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	}, {
		name : "filesize",
		label : "Filesize",
		editable : false,
		cell : Backgrid.StringCell.extend({
			orderSeparator : ''
		})
	}, {
		name : "delete",
		label : "",
		editable : false,
		cell : Backgrid.Cell.extend({
			template : _.template('<button class="btn btn-danger">删除</button>'),
			events : {
				"click" : "onDeleteRow"
			},
			onDeleteRow : function(e) {
				e.preventDefault();
				if(confirm("确定要删除吗？"))
                {
					this.model.destroy({
						success : function(model, response) {
							alert('File deleted successfully!' );
						},
						error: function(error){
								console.log("exception encountered when delete data" );
						}
					});
				}
				return false;
			},
			render : function() {
				this.$el.html(this.template());
				this.delegateEvents();
				return this;
			}
		})
	}];




// Set up a grid to use the pageable collection
window.WineCollectionView = Backbone.View.extend({
	
	grid: Backgrid.Grid,
	
	// The el and model object are passed in when instantiate this object(new this object).
	// model: winelist,
	
	events:{
		'click #addnew': 'onAddnew',
		'click #deleteselected': 'onDeleteSelected',
		'click #httpupload': 'onHttpUpload',
		'click #ftpimport': 'onFtpImport',
	},
	
	initialize: function() {
		console.log("WineCollectionView initialized!");
		
		this.template = _.template($("#tpl_itemlist").html());
		
		/*
		this.model.on("change", this.render, this);
		*/
		
		// this.on("reset", function(collection){
		// 	this.render();
		// });
	},

	render: function(){
		grid = new Backgrid.Grid({
			columns: BackgridColumns,
			collection: this.model 
		});

		//$(this.el).html(this.template(this.model.toJSON()));
		$(this.el).html(this.template());

		$("#backgrid").html( grid.render().el );
		
		var filter = new Backgrid.Extension.ClientSideFilter({
			collection: this.model,
			fields: ['description']
		});
		$("#backgrid").prepend(filter.render().el);
		var paginator = new Backgrid.Extension.Paginator({
			collection: this.model
		});
		$("#backgrid").append(paginator.render().el);
		
		return this;
	},
	
	onAddnew: function(){
		console.log("addnew selected click");
		$('#objecteditor').html( new WineView({model: new NodeModel()}).render().el );
		//app.navigate("wines/", true);
	},
	
	onHttpUpload: function(){
		console.log("httpupload selected click");
		$('#objecteditor').html( new HttpUploadView({model: new HttpUploadModel()}).render().el );
		//app.navigate("wines/", true);
	},
	
	onDeleteSelected: function(){
		console.log("delete selected click");	

		var selectedModels = grid.getSelectedModels();
		if (selectedModels == null) {
			alert("Please select what you want to delete first!");
		} 
		else if (selectedModels.length > 5){
			alert("This application doesn't allow you delete objects more than 5! You could only select at most 5");
		}
		else{
			_.each(selectedModels, function(model) {
				model.destroy({
					success: function(model,response){
						console.log("delete selected successfully " + model );
					},
					error: function(error){
						console.log("exception encountered when delete data" );
					}
				})
			});
		}
	},

	onFtpImport: function(){
        console.log("ftp import click");
        app.navigate("ftp/import",{trigger :true});
	}
});



window.FtpCollectionView = Backbone.View.extend({
	
	grid2: Backgrid.Grid,
   // el :"#objecteditor",

	events:{
		 "click .cancel": "onCancel",
		 "click .import": "onImport"
	},
	
	initialize: function() {
		console.log("ftpCollectionView initialized!");
		
		this.template = _.template($("#tpl_ftpitemlist").html());
		
		//this.$el.html(this.template());
        $(this.el).html(this.template());
		this.model.fetch();

	
     
	   //$(this.el).html(this.template());

		
		//this.model.on("change", this.render, this);

		//$('#objecteditor').html( new FtpView({model: new FtpModel()}).render().el );
		//this.render();
		
	},

	render: function(){

		grid2 = new Backgrid.Grid({
			columns: FtpBackgridColumns,
			collection: this.model 
		});

		$("#ftpbackgrid").html(grid2.render().el );

		var paginator = new Backgrid.Extension.Paginator({
			collection: this.model
		});
		$("#ftpbackgrid").append(paginator.render().el);

		/*
     
	   $(this.el).html(this.template());

       $("ftpbackgrid").html( grid.render().el );
        //$(this.el).html('hhhhhhhhhh');	//$("#ftpbackgrid").html( grid.render().el );
       */

       
		return this;
	},

	onCancel : function(){
		app.navigate('', {trigger :true});
	},

	onImport : function(){
        console.log("enter import file select");
        var selectedModels = grid2.getSelectedModels();
        if(selectedModels.length == 0){
        	alert("请选择一个文件来进行导入");
        }
        else if (selectedModels.length > 1){
        	alert("请注意！只能选择一个文件");
        }
        else{
	        	_.each(selectedModels, function(model) {
	        		model.set({properties: $('#fileproperties').val()});
	        		if(!model.isValid()){
	        			return false;
	        		}
	        		var m=model;
					model.save(null,{
						success: function(res){
                            alert("文件导入成功");
                            m.destroy({
                            	success : function(model, response) {
									alert("FTP内的源文件已删除");
								},
								error: function(error){
									alert('FTP内的源文件删除失败');
								}
                            });
						},
						error: function(error){
							alert("文件导入失败")
						}
					})
				});
        }

	}
});



window.HttpUploadView = Backbone.View.extend({

	    events: {
        "change input": "onInputChange",
		"click .create": "onCreate",
		"click .cancel": "onCancel"
    },

    initialize: function() {
    	this.template = _.template($('#tpl_httpupload').html());
		this.model.on("change", this.render, this);
    },
    
    render: function() {
		$(this.el).html(this.template());
		return this;
    },

    onInputChange: function(event) {
        var target = event.target;
        console.log('changing ' + target.id + ' from: ' + target.defaultValue + ' to: ' + target.value);
    },

	onCreate: function() {
		

	    this.model.set({
	    	properties: $('#uploadfileproperties').val(),
	    });

        if(!this.model.isValid()){
			return false;
		}

		this.model.save(null, {
			success: function(res) {
				alert("save successfully!");
				console.log(res.id);

 			//var selectedFile = document.getElementById('fileupload').files[0];

  
	         /*$('#fileupload').fileupload({
		        dataType: 'json',
		        add: function (e, data) {
		            data.context = $('<p/>').text('Uploading...').appendTo(document.body);
		            data.submit();
		        },
		        done: function (e, data) {
		            data.context.text('Upload finished.');
		        }
		    });
 		//	$('#fileupload').fileupload();
 			//$('#fileupload').fileupload('option','url',config.base2+'nodes/'+res.id+'.dat'+'/data');
 			$('#fileupload').fileupload('add', {files: selectedFile,'url':config.base2+'nodes/'+res.id+'.dat'+'/data'});
 			$('#fileupload').fileupload('send', {files: selectedFile});
 			//$('#fileupload').fileupload('add', {files: selectedFile});
          

				//app.navigate('', {trigger: true});*/
				
				//$('#fileupload').fileupload('add', {files: selectedFile,  });
				//config.base1+'nodes/'+res.id+'.dat'+'/data'
			
				 $('#fileupload').fileupload({
			        url: config.base1+'nodes/'+res.id+'.dat'+'/data',
			        dataType: 'json',
			        done: function (e, data) {
			            $.each(data.result.files, function (index, file) {
			                $('<p/>').text(file.name).appendTo('#files');
			            });
			        },
			        progressall: function (e, data) {
			            var progress = parseInt(data.loaded / data.total * 100, 10);
			            $('#progress .progress-bar').css(
			                'width',
			                progress + '%'
			            );
			        }
			    }).prop('disabled', !$.support.fileInput)
			        .parent().addClass($.support.fileInput ? undefined : 'disabled');

				
			},
			error: function(error){
				console.log("exception encountered when save data" );
			}
		});

		return false;
	},
	
	onCancel : function(){
		app.navigate('', {trigger :true});
	}


});



// Tile is defined an area containing object list, object detail and their related 
// operations. It's an integration of object collection view and object item view
// together.
//
// TODO
//
window.WineTile = Backbone.View.extend({
	
	// The el will be passed when instantiate this object.
	// el: $("#winetile"),
	
	initialize: function() {
		this.template = _.template($("#tpl_winetile").html());

		this.model.fetch({
    		success : function(collection, resq, options){
    			console.log('WineTile Fetch successfully.');
    		}
    	});

	},

	render: function()
	{
		this.$el.html(this.template());
    	var view = new WineCollectionView({el:"#objecteditor", model: this.model});
    	view.render();
	},
});


//------------------------------------------------------------------------------
// Controller Definition
//------------------------------------------------------------------------------

var WineStoreApplication = Backbone.Router.extend({

	// Declare the model variable, so that the view and use it later. 
	// winelist = new window.PageableWineCollectionModel();
	winelist: null,
	
	routes : {
		'' : 'getItemList',
		"wines/new" : "addNew",
		"wines/httpupload" : "httpUpload",
		//"wines/deleteselected" : "deleteSelected",
		"wines/:id" : "editItemDetail",
		"ftp/import" : "ftpImport",
		
	},

	initialize : function() {
		winelist = new window.PageableNodeCollection();
	},
	
	showView : function(selector, view) {
		$(selector).empty();
		$(selector).html(view.render().el);
		this.currentView = view;
		return view;
	},
	
	getItemList: function(){
		// attention: I don't know why the backgrid can display data successfully
		// when passing the model here.
		var winetile = new window.WineTile({el: "#winetile", model: winelist});
		winetile.render();
		
		// attention you cannot call app.showView() because the return value of render()
		// method seems not appropriate.
		//app.showView('#winetile', new WineCollectionView());
	},
	
	editItemDetail : function(id) {
		var wine = winelist.get(id);
		if (wine == null)
		{
			alert("editItemDetail: Failed to get the model object! ");
		}
		else{
			app.showView('#objecteditor', new WineView({model : wine}));
		};
	},
	
	addNew : function() {
		console.log("router add new");
		$('#objecteditor').html( new WineView({model: new NodeModel()}).render().el );
		//app.showView('#objecteditor', new WineView({model : new WineModel()}));
	},

	
	httpUpload : function() {
		console.log("router add new");
		$('#objecteditor').html( new HttpUploadView({model: new HttpUploadModel()}).render().el );
		//app.showView('#objecteditor', new WineView({model : new WineModel()}));
	},

	ftpImport : function(){
       console.log(" router ftp import");
      // $('#objecteditor').html( new FtpView({model: new window.PageableFtpCollectionModel()}).render().el );
       //app.showView('#objecteditor', new FtpCollectionView({model: new window.PageableFtpCollectionModel()}));
    	//$('#objecteditor').html( new WineView({model: new WineModel()}).render().el );
    	$("#objecteditor").empty();
    	ftpview = new FtpCollectionView({el: "#objecteditor", model: new window.PageableFtpFileCollection()});
    	//$("#objecteditor").html(ftpview.render().el);
    	ftpview.render();
	}

});

$(document).ready(function () {
	app = new WineStoreApplication();
	Backbone.history.start();
});
